package com.fastjars.shiro.utils;

import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * PwdUtil
 * 密码工具
 * @author Brant Liu <br> 邮箱：<br>lbf1988@qq.com <br>日期：<br>2018/10/11
 * @version 1.0.0
 */
public class PwdUtil {
    static final String  HEX_CHARS                      = "0123456789abcdef";
    static final String  HASH_ALGORITHM_SHA1            = "SHA-1";
    static final String  HASH_ALGORITHM_MD5             = "md5";
    static final String  CHARSET                        = "UTF-8";
    static final int     HASH_ITERATIONS                = 2;


    static SimpleHash instanceSimpleHash(String account, String password, String salt){
        return new SimpleHash(HASH_ALGORITHM_MD5, password, ByteSource.Util.bytes(account + salt), HASH_ITERATIONS);
    }

    /**
     * 获取32位小写随机字符串（字母+数字）
     * @return
     */
    public static String getSalt(){
        return new SecureRandomNumberGenerator().nextBytes().toHex();
    }

    /**
     * MD5密码二次加密
     * @return
     */
    public static String getPwdToHex(String account, String password, String salt){
        return instanceSimpleHash(account, password, salt).toHex();
    }

    /**
     * MD5密码二次加密
     * @return
     */
    public static String getPwdToBase64(String account, String password, String salt){
        return instanceSimpleHash(account, password, salt).toBase64();
    }

    /**
     * Returns a MessageDigest for the given <code>algorithm</code>.
     * @return An MD5 digest instance.
     */
    static MessageDigest getDigest() {
        try {
            return MessageDigest.getInstance(HASH_ALGORITHM_MD5.toUpperCase());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Calculates the MD5 digest and returns the value as a 16 element
     * @param data
     * @return
     */
    public static byte[] md5(byte[] data) {
        return getDigest().digest(data);
    }

    /**
     * Calculates the MD5 digest and returns the value as a 16 element
     * @param data
     * @param charset
     * @return
     */
    public static byte[] md5(String data, String charset) {
        try {
            return md5(data.getBytes(charset));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Calculates the MD5 digest and returns the value as a 16 element, charset UTF-8
     * @param data
     * @return
     */
    public static byte[] md5(String data) {
        try {
            return md5(data.getBytes(CHARSET));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Calculates the MD5 digest and returns the value as a 32 character hex
     * @param data
     * @return
     */
    public static String md5Hex(byte[] data) {
        return toHexString(md5(data));
    }

    /**
     * Calculates the MD5 digest and returns the value as a 32 character hex
     * @param data
     * @param charset
     * @return
     */
    public static String md5Hex(String data, String charset) {
        return toHexString(md5(data, charset));
    }

    /**
     * Calculates the MD5 digest and returns the value as a 32 character hex
     * @param data
     * @return
     */
    public static String md5Hex(String data) {
        return toHexString(md5(data, CHARSET));
    }

    /**
     * Converts a byte array to hex string.
     * @param b
     * @return
     */
    public static String toHexString(byte[] b) {
        StringBuffer sb = new StringBuffer();
        for (byte aB : b) {
            sb.append(HEX_CHARS.charAt(aB >>> 4 & 0x0F));
            sb.append(HEX_CHARS.charAt(aB & 0x0F));
        }
        return sb.toString();
    }

    /**
     * Converts a hex string into a byte array.
     * @param s
     * @return
     */
    public static byte[] toByteArray(String s) {
        byte[] buf = new byte[s.length() / 2];
        int j = 0;
        for (int i = 0; i < buf.length; i++) {
            buf[i] = (byte) ((Character.digit(s.charAt(j++), 16) << 4) | Character.digit(s.charAt(j++), 16));
        }
        return buf;
    }

    public static String SHA1(String decript) {
        try {
            MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM_SHA1);
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
}
